package com.william.jdbcplus.core.query;

import com.william.jdbcplus.core.conditions.wrap.IWrap;
import com.william.jdbcplus.core.dialects.pagination.PaginationFactory;
import com.william.jdbcplus.core.toolkit.MapTransformUtils;
import com.william.jdbcplus.common.enums.DbType;
import com.william.jdbcplus.common.page.IPage;
import com.william.jdbcplus.common.page.Page;
import com.william.jdbcplus.core.util.JdbcUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 静态包装类
 */
public class WrapUtil {
    /**
     * 从列表中获取一个第一个对象
     *
     * @param list
     * @param <M>
     * @return
     */
    private static <M> M getFirst(List<M> list) {
        if (list == null || list.size() == 0) {
            return null;
        } else {
            return list.get(0);
        }
    }

    /**
     * 根据数据源获取 NamedParameterJdbcTemplate
     *
     * @param ds 数据源
     * @return
     */
    public static NamedParameterJdbcTemplate getTemplate(DataSource ds) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
        NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
        return namedParameterJdbcTemplate;
    }

    /**
     * 查询map列表
     *
     * @param wrap 查询条件
     * @param ds   数据源
     * @return
     */
    public static List<Map<String, Object>> queryMapList(IWrap wrap, DataSource ds) {
        NamedParameterJdbcTemplate jdbcOpt = getTemplate(ds);
        String sql = wrap.getAll();
        Map<String, Object> paramMap = wrap.getParamNameValuePairs();
        List<Map<String, Object>> listMap = jdbcOpt.queryForList(sql, paramMap);
        return listMap;
    }

    /**
     * 查询map
     *
     * @param wrap 查询条件
     * @param ds   数据源
     * @return
     */
    public static Map<String, Object> queryMap(IWrap wrap, DataSource ds) {
        List<Map<String, Object>> list = queryMapList(wrap, ds);
        return getFirst(list);
    }

    /**
     * 查询map分页
     *
     * @param wrap 查询条件
     * @param page 分页参数
     * @param ds   数据源
     * @return
     */
    public static IPage<Map<String, Object>> queryMapPage(IWrap wrap, IPage<?> page, DataSource ds) {
        NamedParameterJdbcTemplate jdbcOpt = getTemplate(ds);
        DbType dbType = JdbcUtil.getDbType(ds);
        Integer totalCount = queryCount(wrap, ds);
        List<Map<String, Object>> listMap = null;
        if (totalCount <= 0) {
            listMap = new ArrayList<>();
        } else {
            String sql = wrap.getAll();
            String sqlPage = PaginationFactory.getPaginationSql(page, sql, dbType);
            listMap = jdbcOpt.queryForList(sqlPage, wrap.getParamNameValuePairs());
        }

        Page<Map<String, Object>> resultPage = new Page<>(page.getCurrent(), page.getSize());
        resultPage.setRecords(listMap);
        resultPage.setTotal(totalCount);
        return resultPage;
    }

    /**
     * 查询数量
     *
     * @param wrap 查询条件
     * @param ds   数据源
     * @return
     */
    public static Integer queryCount(IWrap wrap, DataSource ds) {
        NamedParameterJdbcTemplate jdbcOpt = getTemplate(ds);
        String sqlCount = wrap.getCount();
        Map<String, Object> paramMap = wrap.getParamNameValuePairs();
        Integer count = jdbcOpt.queryForObject(sqlCount, paramMap, Integer.class);
        return count;
    }

    /**
     * 查询一个实体
     *
     * @param wrap  查询条件
     * @param clazz 类
     * @param ds    数据源
     * @param <M>
     * @return
     */
    public static <M> M queryOne(IWrap wrap, Class<M> clazz, DataSource ds) {
        return getFirst(queryList(wrap, clazz, ds));
    }

    /**
     * 查询实体列表
     *
     * @param wrap  查询条件
     * @param clazz 类
     * @param ds    数据源
     * @param <M>
     * @return
     */
    public static <M> List<M> queryList(IWrap wrap, Class<M> clazz, DataSource ds) {
        List<Map<String, Object>> listMap = queryMapList(wrap, ds);
        List<M> resultList = MapTransformUtils.mapToEntityList(listMap, clazz);
        return resultList;
    }

    /**
     * 查询实体分页
     *
     * @param wrap  查询条件
     * @param page  分页参数
     * @param clazz 类
     * @param ds    数据源
     * @param <M>
     * @return
     */
    public static <M> Page<M> queryPage(IWrap wrap, IPage<?> page, Class<M> clazz, DataSource ds) {
        IPage<Map<String, Object>> mapPage = queryMapPage(wrap, page, ds);
        List<Map<String, Object>> mapList = mapPage.getRecords();
        List<M> resultRows = MapTransformUtils.mapToEntityList(mapList, clazz);
        Page<M> pageResult = new Page<>(page.getCurrent(), page.getSize());
        pageResult.setTotal(mapPage.getTotal());
        pageResult.setRecords(resultRows);
        return pageResult;
    }

    /**
     * 查询基本类型列表
     *
     * @param wrap        查询条件
     * @param elementType 基本类型
     * @param ds          数据源
     * @param <T>
     * @return
     */
    public static <T> List<T> queryObjectList(IWrap wrap, Class<T> elementType, DataSource ds) {
        NamedParameterJdbcTemplate jdbcOpt = getTemplate(ds);
        String sql = wrap.getAll();
        Map<String, Object> paramMap = wrap.getParamNameValuePairs();
        List<T> result = jdbcOpt.queryForList(sql, paramMap, elementType);
        return result;
    }

    /**
     * 查询基本类型列表
     *
     * @param wrap        查询条件
     * @param elementType 基本类型
     * @param ds          数据源
     * @param <T>
     * @return
     */
    public static <T> T queryObject(IWrap wrap, Class<T> elementType, DataSource ds) {
        NamedParameterJdbcTemplate jdbcOpt = getTemplate(ds);
        String sql = wrap.getAll();
        Map<String, Object> paramMap = wrap.getParamNameValuePairs();
        T result = jdbcOpt.queryForObject(sql, paramMap, elementType);
        return result;
    }
}
